package com.abso.sunlight.explorer.jobs;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;

import com.abso.sunlight.api.Legislator;
import com.abso.sunlight.api.SunlightException;
import com.abso.sunlight.api.SunlightService;
import com.abso.sunlight.explorer.CongressExplorerPlugin;
import com.abso.sunlight.explorer.LegislatorSearch;
import com.abso.sunlight.explorer.editors.LegislatorListEditor;
import com.abso.sunlight.explorer.editors.LegislatorListEditorInput;

/**
 * A scheduled job able to perform a search over legislators interacting with the remote Sunlight API service.
 */
public class RunLegislatorSearchJob extends Job {

    /** The workbench window. */
    private IWorkbenchWindow window;

    /** The legislator search. */
    private LegislatorSearch search;

    /**
     * Constructs a new job.
     * 
     * @param window   the workbench window.
     * @param search   the legislator search.
     */
    public RunLegislatorSearchJob(IWorkbenchWindow window, LegislatorSearch search) {
        super("Searching legislators");
        setUser(true);
        this.window = window;
        this.search = search;
    }

    @Override
    protected IStatus run(IProgressMonitor monitor) {
        if (monitor.isCanceled()) {
            return Status.CANCEL_STATUS;
        }
        SunlightService service = new SunlightService(CongressExplorerPlugin.API_KEY);
        monitor.beginTask(getName(), IProgressMonitor.UNKNOWN);
        try {

            /* performs the search */
            final List<Legislator> legislators = service.getLegislators(search.getQuery());
            if (monitor.isCanceled()) {
                return Status.CANCEL_STATUS;
            }

            /* opens the result editor */
            CongressExplorerPlugin.getDefault().runUIAsync(window.getShell(), new Runnable() {
                public void run() {
                    try {
                        CongressExplorerPlugin.getSearchManager().setSearchResult(search, legislators);
                        List<IEditorReference> editorRefsToClose = new ArrayList<IEditorReference>();
                        for (IEditorReference editorRef : window.getActivePage().getEditorReferences()) {
                            IEditorInput editorInput = editorRef.getEditorInput();
                            if (editorInput instanceof LegislatorListEditorInput) {
                                LegislatorSearch editorSearch = ((LegislatorListEditorInput) editorInput).getSearch();
                                if (editorSearch == search) {
                                    editorRefsToClose.add(editorRef);
                                }
                            }
                        }
                        if (!editorRefsToClose.isEmpty()) {
                            window.getActivePage().closeEditors(editorRefsToClose.toArray(new IEditorReference[0]), false);
                        }
                        window.getActivePage().openEditor(new LegislatorListEditorInput(search), LegislatorListEditor.ID, true,
                                IWorkbenchPage.MATCH_NONE);
                    } catch (PartInitException e) {
                        CongressExplorerPlugin.getDefault().showErrorDialog(window.getShell(), "Error", "Unable to show results",
                                e.getMessage(), e);
                    }
                }
            });
        } catch (SunlightException e) {
            if (monitor.isCanceled()) {
                return Status.CANCEL_STATUS;
            }
            CongressExplorerPlugin.getDefault().showErrorDialog(window.getShell(), "Error", "Unable to search legislators",
                    e.getMessage(), e);
        } finally {
            monitor.done();
        }
        return Status.OK_STATUS;
    }

}
